#include "tcp_server.h"



tcp_server::tcp_server()
{
	try
	{
		std::string configFilePath = "./config/tcp_server_config.json";
		Json::Value root;
		Json::Reader reader;
		std::ifstream configFile(configFilePath, std::ifstream::binary);
		bool parsingSuccessful = reader.parse(configFile, root);
		if (!parsingSuccessful) {
			std::cerr << "Failed to parse configuration file(grpc)\n\a" << std::endl;
			exit(-1);
		}
		int port = root["port"].asInt();


		io_service_sp = std::make_shared<io_service>();
		acceptor_sp = std::make_shared<acceptor>(
			*io_service_sp,
			endpoint(boost::asio::ip::tcp::v4(), port)
		);
	}
	catch (const boost::system::system_error& e)
	{
		if (e.code() == boost::asio::error::address_in_use) {
			std::cerr << "Port 6688 is already in use. Exiting..." << std::endl;
			exit(EXIT_FAILURE);
		}
		else {
			std::cerr << "Other error: " << e.what() << " Exiting..." << std::endl;
			exit(EXIT_FAILURE);
		}

	}
}
tcp_server::~tcp_server() {}

void tcp_server::run()
{
	accept();
	io_service_sp->run();
}

void tcp_server::accept()
{
	socket_shared_ptr sock = std::make_shared<socket>(*io_service_sp);
	acceptor_sp->async_accept(*sock,
		boost::bind(
			&tcp_server::accept_handler,
			this,
			boost::asio::placeholders::error,
			sock
		)
	);

}
void tcp_server::accept_handler(const boost::system::error_code& ec, socket_shared_ptr sock)
{
	if (ec) {
		this->accept();
		return;
	}
	std::cout << "Client : ";
	std::cout
		<< sock->remote_endpoint().address().to_string()
		<< ":"
		<< sock->remote_endpoint().port()
		<< " joined..."
		<< std::endl;
	sock->write_some(boost::asio::buffer("StackChat"));

	std::string sock_name =
		sock->remote_endpoint().address().to_string() +
		":" +
		std::to_string(sock->remote_endpoint().port());
	sessions.push_back(std::make_pair(sock_name, sock));

	print_sessions();

	this->accept();
	this->read(sock);
}


void tcp_server::read(socket_shared_ptr sock) {
	auto buf = std::make_shared<std::vector<char>>(10240);
	sock->async_read_some(
		boost::asio::buffer(*buf),
		boost::bind(
			&tcp_server::read_handler,
			this,
			boost::asio::placeholders::error,
			boost::asio::placeholders::bytes_transferred,
			buf,
			sock
		)
	);
}


void tcp_server::read_handler(const boost::system::error_code& error,
	std::size_t bytes_transferred,
	std::shared_ptr<std::vector<char>> buffer,
	socket_shared_ptr sock) {
	if (!error) {
		// 处理接收到的数据
		std::string msg = std::string(buffer->begin(), buffer->begin() + bytes_transferred);
		std::cout << "Received data: "
			<< msg
			<< " ("
			<< sock->remote_endpoint().address().to_string()
			<< ":"
			<< sock->remote_endpoint().port()
			<< ") "
			<< std::endl;
		auto res = jmp.DistributeServer(msg);
		std::cout << res << "res" << std::endl;
		reader.parse(res, root);
		if (root["jsonID"].asString() == "12" && root["jsonData"]["status"] == 1)
		{
			reader.parse(msg, root);
			int user_id = root["jsonData"]["user_id"].asInt();
			for (auto& s : sessions)
			{
				if (s.second == sock)
					s.first = std::to_string(user_id);
			}
		}
		if (root["jsonID"].asString() == "22" && root["jsonData"]["status"] == 1)
		{
			reader.parse(msg, root);
			int receive_id = root["jsonData"]["receive_id"].asInt();;
			for (auto s : sessions)
			{
				if (s.first == std::to_string(receive_id))
				{
					s.second->write_some(boost::asio::buffer(msg));
				}
			}
		}
		print_sessions();
		read(sock);
	}
	else {
		std::cerr
			<< "Client : "
			<< sock->remote_endpoint().address().to_string()
			<< ":"
			<< sock->remote_endpoint().port()
			<< " disconnect..."
			<< std::endl;

		for (auto it = sessions.begin();
			it != sessions.end();
			++it)
		{
			if (it->second == sock) {
				sessions.erase(it);
				break; // 找到并删除会话后退出循环
			}
		}

	}
}

void tcp_server::print_sessions()
{
	std::cout << "All current sessions : " << std::endl;
	for (auto c : sessions)
	{
		std::cout << c.first << ";" << std::endl;
	}
}

void tcp_server::print_tcp_server_message()
{
	std::cout
		<< "Tcp Server address : "
		<< acceptor_sp->local_endpoint().address()
		<< std::endl
		<< "Tcp Server port : "
		<< acceptor_sp->local_endpoint().port()
		<< std::endl;
}